package main

import (
	"context"
	"github.com/cloudwego/hertz/pkg/app"
	"github.com/cloudwego/hertz/pkg/app/server"
	"github.com/cloudwego/hertz/pkg/network/netpoll"
	"github.com/go-redis/redis"
	"github.com/tendermint/tendermint/my_test/performance/utils"
	"github.com/tendermint/tendermint/rpc/client/http"
	"strconv"
	"strings"
	"time"
)

var (
	cli *http.HTTP
	r   *redis.Client
)

func init() {
	var err error

	cli, err = http.New("http://127.0.0.1:26657", "/websocket")
	if err != nil {
		panic(err)
	}

	r = redis.NewClient(&redis.Options{
		Addr:         "127.0.0.1:6379",
		Password:     "123456",
		MinIdleConns: 12800,
		PoolSize:     25600,
		IdleTimeout:  -1,
	})
	if _, err = r.Ping().Result(); err != nil {
		panic(err)
	}

	utils.Preheat(cli, r, context.TODO())
}

func NewRouter(addr string) *server.Hertz {
	h := server.Default(
		server.WithHostPorts(addr),
		server.WithKeepAlive(true),
		server.WithIdleTimeout(time.Minute*5),
		server.WithTransport(netpoll.NewTransporter),
	)

	h.GET("/prov_range", func(c context.Context, ctx *app.RequestContext) {
		minObjectIdStr := ctx.Query("min")
		maxObjectIdStr := ctx.Query("max")

		minObjectId, err := strconv.Atoi(minObjectIdStr)
		if err != nil {
			ctx.String(200, err.Error())
			return
		}

		maxObjectId, err := strconv.Atoi(maxObjectIdStr)
		if err != nil {
			ctx.String(200, err.Error())
			return
		}

		keys := make([]string, 0, maxObjectId-minObjectId+1)

		for id := minObjectId; id <= maxObjectId; id++ {
			keys = append(keys, strconv.Itoa(id))
		}

		results, err := r.MGet(keys...).Result()
		if err != nil {
			ctx.String(200, err.Error())
			return
		}

		var res strings.Builder
		res.Grow((maxObjectId - minObjectId + 1) * 1024) // 预分配缓冲区

		for _, result := range results {
			if result != nil {
				res.WriteString(result.(string) + "\n\n")
			}
		}

		ctx.String(200, res.String())
	})

	h.GET("/prov", func(c context.Context, ctx *app.RequestContext) {
		objectId := ctx.Query("object_id")

		res, err := r.Get(objectId).Result()
		if err != nil {
			ctx.String(200, err.Error())
			return
		}

		ctx.String(200, res)
	})

	return h
}

func main() {
	hertz := NewRouter(":9999")
	hertz.Spin()
}
